package com.sc.core.make.file;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.sc.core.make.MasterMake;
import com.sc.core.make.dto.MakeInfoColumnDTO;
import com.sc.core.make.dto.MakeInfoDTO;
import com.sc.core.make.file.template.Form;
import com.sc.core.make.file.template.Lists;
import com.sc.core.make.vo.TableColumn;
import lombok.Getter;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.configurationprocessor.json.JSONObject;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;

@Log4j2
public class Template implements IFileMake{

    @Getter
    private String message = "成功";

    private final MakeInfoDTO makeInfo;
    private final Map<String, Map<Integer, String>> enumMap;

    public Template(MakeInfoDTO makeInfo, Map<String, Map<Integer, String>> enumMap) {
        this.makeInfo = makeInfo;
        this.enumMap = enumMap;
    }

    @Override
    public IFileMake make() {

        makeForm();
        makeList();

        return this;
    }


    private void makeForm() {
        String content = Form.content;
        content = content.replace("<identity>", makeInfo.getIdentity());
        content = content.replace("<module>", makeInfo.getModuleName());
        content = formEnumOptionsReplace(content);

        Map<String, Object> defaultValue = new LinkedHashMap<>();
        ArrayList<String> columns = new ArrayList<>();
        makeInfo.getColumns().forEach(tableColumn -> {
            if (MasterMake.PRIMARY.equals(tableColumn.columnName())) {
                defaultValue.put(tableColumn.columnName(), null);
                columns.add(getFormItemContent(tableColumn));
                return;
            }else if(MasterMake.CREATE_AT.equals(tableColumn.columnName()) || MasterMake.UPDATE_AT.equals(tableColumn.columnName()) || MasterMake.DELETE_AT.equals(tableColumn.columnName())){
                return;
            }
            defaultValue.put(tableColumn.columnName(), tableColumn.columnDefault());
            columns.add(getFormItemContent(tableColumn));
        });

        content = content.replace("<default>", new JSONObject(defaultValue).toString()
                .replaceAll("\"(\\d+)\"", "$1")
                .replace(",", ",\n" + MasterMake.retraction(5))
                .replace("{", "{\n" + MasterMake.retraction(5))
                .replace("}", "\n" + MasterMake.retraction(4) + "}")
        );

        content = content.replace("<items>", String.join(MasterMake.retraction(5), columns));
        String res = MasterMake.writeFile(getTemplateFilePath("form.html"), content);
        message = message.equals("成功")
                ? "Form" + res
                : message + "Form(失败)" + res;
    }

    private String formEnumOptionsReplace(String content) {
        StringBuilder options = new StringBuilder();
        StringBuilder optionsDef = new StringBuilder();
        for (Map.Entry<String, Map<Integer, String>> entry : enumMap.entrySet()){
            optionsDef.append(String.format("enumOptions.%s = ref([]);\n", entry.getKey()));
            options.append(String.format("%s: enumOptions.%1$s,\n", entry.getKey()));
        }
        content = content.replace("<options>", options.toString());
        content = content.replace("<optionsDef>", optionsDef.toString());
        return content;
    }

    private String listEnumOptionsReplace(String content) {
        StringBuilder enumRequestCode = new StringBuilder();
        StringBuilder options = new StringBuilder();
        StringBuilder optionsDef = new StringBuilder();
        for (Map.Entry<String, Map<Integer, String>> entry : enumMap.entrySet()){
            optionsDef.append(String.format("const %s = ref([]);\n", entry.getKey()));
            options.append(String.format("%s,\n", entry.getKey()));
            enumRequestCode.append(Lists.enumRequest
                    .replace("<identity>", makeInfo.getIdentity())
                    .replace("<enumName>", entry.getKey())
                    .replace("<module>", makeInfo.getModuleName())
            );
        }
        content = content.replace("<options>", options.toString());
        content = content.replace("<optionsDef>", optionsDef.toString());
        content = content.replace("<enumRequest>", enumRequestCode.toString());
        return content;
    }

    private void makeList() {
        String content = Lists.content;
        content = content.replace("<identity>", makeInfo.getIdentity());
        content = content.replace("<module>", makeInfo.getModuleName());
        content = listEnumOptionsReplace(content);

        ArrayList<String> columns = new ArrayList<>();
        makeInfo.getColumns().forEach(tableColumn -> {
            if (MasterMake.PRIMARY.equals(tableColumn.columnName())) {
                columns.add(getListColumnContent(tableColumn));
                return;
            }else if(MasterMake.CREATE_AT.equals(tableColumn.columnName()) || MasterMake.UPDATE_AT.equals(tableColumn.columnName()) || MasterMake.DELETE_AT.equals(tableColumn.columnName())){
                return;
            }
            columns.add(getListColumnContent(tableColumn));
        });

        content = content.replace("<items>", String.join(MasterMake.retraction(2), columns));

        String res = MasterMake.writeFile(getTemplateFilePath("list.html"), content);
        message = message.equals("成功")
                ? "List" + res
                : message + "List(失败)" + res;
    }


    private String getFormItemContent(MakeInfoColumnDTO tableColumn) {
        StringBuilder sb = new StringBuilder();
        sb.append("FI.").append(tableColumn.formType());
        sb.append("('").append(tableColumn.columnName()).append("','").append(tableColumn.columnComment()).append("')");

        enumMap.forEach((key, value) -> {
            if (key.equals(tableColumn.columnName())) {
                sb.append(String.format(".options('%s')", key));
            }
        });

        return sb.append(',').append(MasterMake.BR).toString();
    }

    private String getTemplateFilePath(String filename) {
        List<String> packageDir = new ArrayList<>(Arrays.asList(MasterMake.getPackageDir("admin"), "src", "main", "resources", "templates"));
        packageDir.add(makeInfo.getModuleName());
        packageDir.add(makeInfo.getIdentity());
        packageDir.add(filename);
        return String.join(File.separator, packageDir);
    }

    private String getListColumnContent(MakeInfoColumnDTO tableColumn) {
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("<el-table-column prop=\"%s\" label=\"%s\" >", tableColumn.columnName(), tableColumn.columnComment()));
        if (enumMap.containsKey(tableColumn.columnName())) {
            sb.append(MasterMake.BR).append(MasterMake.retraction(3));
            sb.append("<template #deault=\"scope\">");
            sb.append(MasterMake.BR).append(MasterMake.retraction(4));
            sb.append(String.format("<template v-for=\"(item, index) in %s\">", tableColumn.columnName()));
            sb.append(MasterMake.BR).append(MasterMake.retraction(5));
            sb.append(String.format("<el-tag :key=\"item.value\" v-if=\"scope.row.%s == item.value\"  v-bind=\"theme[index]\">{{ item.desc }}</el-tag>", tableColumn.columnName()));
            sb.append(MasterMake.BR).append(MasterMake.retraction(4));
            sb.append("</template>");
            sb.append(MasterMake.BR).append(MasterMake.retraction(3));
            sb.append("</template>");
            sb.append(MasterMake.BR).append(MasterMake.retraction(2));
        }
        sb.append("</el-table-column>");
        sb.append(MasterMake.BR);
        return sb.toString();
    }
}
